/*
 * Package il.ac.biu.cs.grossmm.api.keys
 * File KeyFactory.java
 * Created on Sep 5, 2006
 *
 */
package il.ac.biu.cs.grossmm.api.keys;

import java.util.WeakHashMap;

/**
 * Creates keys using default implementations. This class uses key-caching
 * mechanism which significatly improves performance by avoiding object
 * allocation when possibe.
 */
public class KeyFactory {
	static WeakHashMap<Key, Key> cache = new WeakHashMap<Key, Key>();

	/**
	 * Creates a key with a given value and set of key entries.
	 * 
	 * @param value
	 *            the key value
	 * @param entries
	 *            the entries containing the subkeys
	 * @return the constructed key
	 */
	public static Key key(Object value, KeyEntry... entries)
	{
		Key key =
			entries.length > 4 ? new ArrayKey(value, entries) : new SmallKey(
				value, entries);

		Key cached = cache.get(key);
		if (cached == null) {
			cache.put(key, key);
			return key;
		} else
			return cached;
	}

	/**
	 * Creates a key with a null value and set of key entries.
	 * 
	 * @param entries
	 *            the entries containing the subkeys
	 * @return the constructed key
	 */
	public static Key key(KeyEntry... entries)
	{
		return key(null, entries);
	}

	/**
	 * Creates a key entry with a given attribute and key.
	 * 
	 * @param attribute
	 *            the attribute
	 * @param entries
	 *            the (sub)key
	 * @return the constructed key
	 */
	public static KeyEntry entry(Attribute attribute, Key key)
	{
		if (key == null)
			return entry(attribute, (Object) null);
		return new KeyEntry(attribute, key);
	}

	/**
	 * Creates a key entry with a given attribute and value of a simple key.
	 * 
	 * @param attribute
	 *            the attribute
	 * @param value
	 *            the value of a simple key to associate with this entry
	 * @return the constructed key
	 */
	public static KeyEntry entry(Attribute attribute, Object value)
	{
		return new KeyEntry(attribute, key(value));
	}

	/**
	 * Creates a key entry with a given attribute and NULL key
	 * 
	 * @param attribute
	 *            the attribute
	 * @return the constructed key
	 */
	public static KeyEntry entry(Attribute attribute)
	{
		return new KeyEntry(attribute, Key.NULL);
	}

	// operations

	/**
	 * Creates a new key with all entries in a given existing key and the given
	 * entry (replaces the entry with the same attribute in the existing key, if
	 * such entry exists). This operation does not change key provided as an
	 * argument.
	 * 
	 * @param key
	 *            the base key
	 * @param entriey
	 *            key entry to add
	 */
	public static Key insert(Key key, KeyEntry entry)
	{
		return new ArrayKey(key, entry);
	}

	/**
	 * Creates a new key based on existing key with a set of key-entries added.
	 * This operation does not change key provided as an argument.
	 * 
	 * @param key
	 *            the base key
	 * @param entries
	 *            key entries to add
	 */
	public static Key insert(Key key, KeyEntry... entries)
	{
		return new ArrayKey(key, entries);
	}
}
